/* http.c */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "http.h"

static char *find_line_end(char *req, int len)
{
  char *p = req;
  int state = 0;

  while (p - req < len) {
    if (state == 0 && *p == '\r')
      state = 1;
    else if (state == 1 && *p == '\n')
      return p - 1;
    p++;
  }
  return NULL;
}

/**
 * Extract HTTP headers from a request, calling func() once for each
 * header found.
 *
 * If endp is not NULL, *endp is set to point to the end of the
 * consumed data.
 *
 * Return value:
 *  = 0 if the extraction is complete, that is, there are no more
 *    headers to be extracted (although there may be other data after
 *    *endp).
 *  = 1 if the extraction was not completed because the request is not
 *    complete, that is, you should keep reading request data from the
 *    network.
 *  = -1 if func() returns non-zero. In this case, *endp is set to the
 *    start of the header that caused the function call that returned
 *    non-zero.
 */
int http_extract_headers(char *req, int len, char **endp, http_header_callback func, void *data)
{
  char *pos;

  pos = req;
  while (pos - req < len) {
    char *end, *colon;
    int ret;

    end = find_line_end(pos, len - (pos - req));
    if (! end) {
      if (endp) *endp = pos;
      return 1;
    }
    if (end == pos) {
      if (endp) *endp = end + 2;
      return 0;
    }
    *end = '\0';
    
    colon = strchr(pos, ':');
    if (! colon) 
      ret = func(pos, NULL, data);
    else {
      *colon++ = '\0';
      while (*colon == ' ' || *colon == '\t')
	colon++;
      ret = func(pos, colon, data);
    }

    if (ret) {
      if (endp) *endp = pos;
      return -1;
    }
    pos = end + 2;
  }

  if (endp) *endp = pos;
  return 1;
}

